package cn.sinjet.model.mcuupgrade;

import android.content.Context;
import android.util.Log;
import com.mgroup.wazehelper.R;
import cn.sinjet.carassist.SinjetApplication;
import cn.sinjet.communication.bluetooth.BTWorkingHandler;
import cn.sinjet.communication.bluetooth.BluetoothModel;
import cn.sinjet.model.carassist.AppModel;
import cn.sinjet.model.carsystem.CarModel;
import cn.sinjet.myview.EditTextAlertDlg;
import cn.sinjet.myview.EditTextAlertDlg.OnEditTextDlgActionListener;
import cn.sinjet.utils.SharedPreferenceUtil;
import cn.sinjet.utils.ShowDialogUtil;
import cn.sinjet.utils.ShowDialogUtil.OnDialogAction;
import cn.sinjet.viewmodel.PageDefine;
import cn.sinjet.viewmodel.ViewModel;

enum enumMCUNowIsRunning {
	enumMCUNowIsRunningBootloader,
	enumMCUNowIsRunningSystem,
	enumMCUNowIsRunningMax
}

enum enumMCUBootloaderStatus {
	enumMCUSystemStatusIdle,
	enumMCUBootloaderStatusIdle,
	enumMCUBootloaderStatusUpdateIng,
	enumMCUBootloaderStatusUpdateSuccess,
	enumMCUBootloaderStatusUpdateFailAddressError,
	enumMCUBootloaderStatusUpdateFailCRCError,
	enumMCUBootloaderStatusUpdateFailMagicStringError,
	enumMCUBootloaderStatusMax
}

enum enumFrameReqMode{
	enumFrameReqModeNormal,
	enumFrameReqModeLost,
	enumFrameReqModeMax
}

enum enumUpgradeHexType{
	enumUpgradeHexTypeSystem,
	enumUpgradeHexTypeBootloader,
	enumUpgradeHexTypeMax
}

public class McuUpgradeModel implements DownloadStatusCallBack {
	static final int haveCustomStringVersion = 20160510;
	private static McuUpgradeModel upgradeModel = null;
	public synchronized static McuUpgradeModel getInstance(){
		if(upgradeModel == null)
			upgradeModel = new McuUpgradeModel();
		return upgradeModel;
	}
	
	String magicStringMCUString = null;
	int versionMCU = 0;
	String mcuSystemFileName;
	String mcuBootloaderFileName;
	String mcuSystemReqFlag;
	String mcuBootloaderReqFlag;
	String upgradePassword = null;
	
	private int versionServiceSystem = 0;
	private int versionServiceBootloader = 0;
	
	private String strUpdateContent;

	private MCUFileRead mcuFileSystemRead;
	private MCUFileRead mcuFileBootloaderRead;
	public McuUpgradeModel() {
		mcuFileSystemRead = new MCUFileRead();
		mcuFileBootloaderRead = new MCUFileRead();
	}
	
	public void showMCUUpgradeTips(String content){
		Log.d("dialog", "showUpgradeDialog");
		ShowDialogUtil dialogUtil = new ShowDialogUtil();
		dialogUtil.setButtonText("去看看", "下次吧");
		dialogUtil.setOnDialogActionListern(new OnDialogAction() {
			
			@Override
			public void onPositive() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onPositive");
				ViewModel.getIns().jumpPage(PageDefine.PAGE_ABOUT);
			}
			
			@Override
			public void onNegative() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onNegative");
			}
		});
		dialogUtil.showDialog("有新的固件哦", content);
		
	}
	
	boolean haveShowUpgradeTips = false;
	private boolean isCorrectUpgradeFile() {
		if (!mcuFileSystemRead.isValidFile(magicStringMCUString)) {
			return false;
		}
		if (magicStringMCUString == null || !magicStringMCUString.equals(mcuFileSystemRead.magicStringFind))
		{
			return false;
		}
		if (versionMCU == 0)
		{
			return false;
		}
		if (mcuFileSystemRead.version > versionServiceSystem) {
			return false;
		}
		if (mcuFileSystemRead.version <= versionMCU)
		{
			return false;
		}

		if (!haveShowUpgradeTips)
		{
			if (magicStringMCUString.equals("HUDANSK0") || magicStringMCUString.equals("HUDA6AS0"))
			{
				haveShowUpgradeTips = true;
				SharedPreferenceUtil util = new SharedPreferenceUtil(SinjetApplication.getInstance());
				int savedServiceVersion = util.getServiceMCUVersion();
				if (savedServiceVersion != versionServiceSystem)
				{
					util.setServiceMCUVersion(versionServiceSystem);
					//showMCUUpgradeTips(strUpdateContent);
				}
			}
		}
		
		return true;
	}
	
	public void checkUpgradeFile() {
		MCUFetchHex MCUFetchSystemInfo = new MCUFetchHex();
		MCUFetchSystemInfo.checkNewFile(McuUpgradeModel.this,
				upgradePassword,
				mcuSystemReqFlag,mcuSystemFileName,
				true,mcuFileSystemRead.version);
		
		MCUFetchHex MCUFetchBootloaderInfo = new MCUFetchHex();
		MCUFetchBootloaderInfo.checkNewFile(McuUpgradeModel.this,
				upgradePassword,
				mcuBootloaderReqFlag,mcuBootloaderFileName,
				false,0);
	}

	private void showUpgradeDialog(String content){
		Log.d("dialog", "showUpgradeDialog");
		ShowDialogUtil dialogUtil = new ShowDialogUtil();
		dialogUtil.setButtonText("升级", "以后再说");
		dialogUtil.setOnDialogActionListern(new OnDialogAction() {
			
			@Override
			public void onPositive() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onPositive");
				letMCUGoBootloader();
			}
			
			@Override
			public void onNegative() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onNegative");
			}
		});
		dialogUtil.showDialog("升级固件", content);		
	}

	private void upgradePasswordShowEditText(Context context){
		EditTextAlertDlg pswAlertDlg = new EditTextAlertDlg(context);
		pswAlertDlg.setButtonText("确定", "取消");
		pswAlertDlg.show("请输入密码", new OnEditTextDlgActionListener() {
			
			@Override
			public void onPositive(String input) {
				// TODO Auto-generated method stub
				Log.i("test","input:"+input);
				upgradePassword = input;
				haveFetchMCUFile = false;
				needRefetchFile = true;
				reqMCUNowStatus();
			}
			
			@Override
			public void onNegative() {
				// TODO Auto-generated method stub
				Log.i("test","cancel");
			}
			
			@Override
			public void onDismiss() {
				// TODO Auto-generated method stub
				Log.i("test","onDismiss");
			}
		});
	}

	private void showUUIDDialog(String content){
		Log.d("dialog", "showUUIDDialog");
		ShowDialogUtil dialogUtil = new ShowDialogUtil();
		dialogUtil.setButtonText("确定", "升级密码");
		dialogUtil.setOnDialogActionListern(new OnDialogAction() {
			
			@Override
			public void onPositive() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onPositive");
			}
			
			@Override
			public void onNegative() {
				// TODO Auto-generated method stub
				Log.d("dialog", "onNegative");
				upgradePasswordShowEditText(ViewModel.getIns().getCurContext());
	    	}
		});
		dialogUtil.showDialog("模块UUID", content);
		
	}

	int clickCount = 0;
	public void startUpgrade() {
		if (isCorrectUpgradeFile()) {
			StringBuilder content;
			content = new StringBuilder("当前：");
			content.append(String.format("%d", versionMCU));
			content.append("\r\n");
			
			content.append("可更新到：");
			content.append(String.format("%d", mcuFileSystemRead.version));			
			content.append("\r\n");
			
			content.append(strUpdateContent);
			content.append("\r\n");
			
			content.append("\r\n");
			content.append("升级中不要退出APP，不要离开！");
			content.append("\r\n");
			content.append("升级中不要退出APP，不要离开！");
			content.append("\r\n");
			content.append("升级中不要退出APP，不要离开！");

			showUpgradeDialog(content.toString());
		}
		else 
		{
			clickCount++;
			if (clickCount >= 10)
			{
				clickCount = 0;
				if (CarModel.getInstance().devModule.getMcuUUID() != null)
				{
					showUUIDDialog(CarModel.getInstance().devModule.getMcuUUID());
				}
			}		
		}
	}
     
	private void packAndMsg(byte[] message,int len) {
		byte[] szMsg = new byte[len + 5];
		szMsg[0] = (byte) 0xFF;
		szMsg[1] = (byte) 0x55;
		szMsg[2] = (byte) (len + 1);
		szMsg[3] = (byte) 0x37;
		System.arraycopy(message, 0, szMsg, 4, len);
		
		byte sum = 0;
		int s = 0;
		int i = 0;
		for (i = 2; i < len + 4; i++) {
			s += (szMsg[i] & 0xFF);
		}
		sum = (byte) (s & 0xFF);
		szMsg[len + 4] = sum;
		BluetoothModel.getInstance().sendMessage(szMsg);
		
		final StringBuilder stringBuilder = new StringBuilder(len);
		for (byte byteChar : message)
			stringBuilder.append(String.format("%02X ", byteChar));
		Log.d("mcu_upgrade","onSend: "+ stringBuilder.toString());
	}
	public byte[] lastMsg;
	private void packAndMsgUseSelectID(byte selectID,byte[] message,int len) {
		byte[] szMsg = new byte[len + 5];
		szMsg[0] = (byte) 0xFF;
		szMsg[1] = (byte) 0x55;
		szMsg[2] = (byte) (len + 1);
		szMsg[3] = (byte) selectID;
		System.arraycopy(message, 0, szMsg, 4, len);
		
		byte sum = 0;
		int s = 0;
		int i = 0;
		for (i = 2; i < len + 4; i++) {
			s += (szMsg[i] & 0xFF);
		}
		sum = (byte) (s & 0xFF);
		szMsg[len + 4] = sum;
		lastMsg = szMsg;
		BluetoothModel.getInstance().sendMessage(szMsg);
		
		final StringBuilder stringBuilder = new StringBuilder(message.length);
		for (byte byteChar : message)
			stringBuilder.append(String.format("%02X ", byteChar));
		Log.d("mcu_upgrade","onSend: "+ stringBuilder.toString());
	}
	
	private void reqMCUNowStatus() {
		byte[] buf = new byte[2];
		buf[0] = 0x10;
		buf[1] = 0x00;
		packAndMsg(buf,buf.length);
	}

	private void letMCUGoBootloader() {
		byte[] buf = new byte[3];
		buf[0] = 0x10;
		buf[1] = 0x01;
		buf[2] = 0x00;
		packAndMsg(buf,buf.length);
	}

	/*
	private void letMCUGoSystem() {
		byte[] buf = new byte[3];
		buf[0] = 0x10;
		buf[1] = 0x01;
		buf[2] = 0x01;
		packAndMsg(buf,buf.length);
	}
	*/
	
	private void sendUpgradeSystemFileInfo() {
		if (mcuFileSystemRead.isValidFile(magicStringMCUString)) {
			int fileSize,fileCRC;
			
			fileSize = mcuFileSystemRead.binData.length;
			fileCRC = mcuFileSystemRead.binCRC;
			
			byte[] buf = new byte[1+4+4+1];
			buf[0] = 0x20;
			
			buf[1] = (byte)(fileSize & 0xff);
			buf[2] = (byte)((fileSize >> 8) & 0xff);
			buf[3] = (byte)((fileSize >> 16) & 0xff);
			buf[4] = (byte)((fileSize >> 24) & 0xff);
			
			buf[5] = (byte)(fileCRC & 0xff);
			buf[6] = (byte)((fileCRC >> 8) & 0xff);
			buf[7] = (byte)((fileCRC >> 16) & 0xff);
			buf[8] = (byte)((fileCRC >> 24) & 0xff);
			
			buf[9] = 0x01;//force bin
			
			packAndMsg(buf,buf.length);		
		}
	}

	private void sendUpgradeBootloaderFileInfo() {
		if (versionServiceBootloader > 0
				&& versionMCU >= versionServiceBootloader
				&& mcuFileBootloaderRead.haveBinData()
				&& magicStringMCUString != null
				&& magicStringMCUString.equals(mcuFileBootloaderRead.magicStringNeed)) {
			int fileSize,fileCRC;
			
			fileSize = mcuFileBootloaderRead.binData.length;
			fileCRC = mcuFileBootloaderRead.binCRC;
			
			byte[] buf = new byte[1+4+4+1];
			buf[0] = 0x28;
			
			buf[1] = (byte)(fileSize & 0xff);
			buf[2] = (byte)((fileSize >> 8) & 0xff);
			buf[3] = (byte)((fileSize >> 16) & 0xff);
			buf[4] = (byte)((fileSize >> 24) & 0xff);
			
			buf[5] = (byte)(fileCRC & 0xff);
			buf[6] = (byte)((fileCRC >> 8) & 0xff);
			buf[7] = (byte)((fileCRC >> 16) & 0xff);
			buf[8] = (byte)((fileCRC >> 24) & 0xff);
			
			buf[9] = 0x01;//force bin
			
			packAndMsg(buf,buf.length);		
		}
	}
	
	//////////////////////////////////////////////////////////////////frame send logic start
	
	int frameIndexNow = 0;
	int frameCountNow = 0;
	
	int frameSizeNow = 0;
	private void frameSizeSet (int frameSize) {
		frameSizeNow = frameSize;
	}
	
	int frameSendDelayMul = 1;
	private int frameSizeGet () {
		if (frameSizeNow >= 75)
		{
			frameSendDelayMul = 4;
			return 75 - 2;
		}
		else if (frameSizeNow >= 55)
		{
			frameSendDelayMul = 3;
			return 55 - 2;
		}
		else if (frameSizeNow >= 35)
		{
			frameSendDelayMul = 2;
			return 35 - 2;
		}
		else if (frameSizeNow >= 15)
		{
			frameSendDelayMul = 1;
			return 15 - 2;
		}
		else
		{
			frameSendDelayMul = 1;
			return frameSizeNow - 2;
		}
	}
	
	int frameSendDelayTime = BTWorkingHandler.BT_MSG_SEND_DELAY_TIME;
	int frameSendDelayErrorCount = 0;
	private int frameSendDelayGood(int delayMode) {
		int timeLast;
		int timeConst;
		if (0 == delayMode) {
			if (frameSendDelayTime > BTWorkingHandler.BT_MSG_SEND_UPGRADE_FILE_DELAY_TIME) {
				frameSendDelayTime--;				
			}
		}
		else if (1 == delayMode) {
		}
		else if (2 == delayMode) {
			if (frameSendDelayTime < 33*(frameSendDelayMul+1))
			{
				frameSendDelayTime += 10;
			}
			frameSendDelayErrorCount++;
		}
		
		if (frameSendDelayErrorCount > 0)
		{
			frameSendDelayErrorCount--;
			timeLast = 33*(frameSendDelayMul+1);
		}
		else {
			timeLast = (frameSendDelayTime+5)*frameSendDelayMul;
		}
		
		if (BluetoothModel.getInstance().btWorkingHandler.msgBuffCount > 8) {
			timeConst = 600;
		}
		else if (BluetoothModel.getInstance().btWorkingHandler.msgBuffCount > 9) {
			timeConst = 700;
		}
		else if (BluetoothModel.getInstance().btWorkingHandler.msgBuffCount > 10) {
			timeConst = 800;
		}
		else if (BluetoothModel.getInstance().btWorkingHandler.msgBuffCount > 11) {
			timeConst = 900;
		}
		else if (BluetoothModel.getInstance().btWorkingHandler.msgBuffCount > 12) {
			timeConst = 1000;
		}
		else {
			timeConst = 0;
		}
		
		if (timeConst > timeLast) {
			return timeConst;
		}
		return timeLast;
	}
	
	public boolean isUpgradeFrameData(byte[] message) {
		if (0x38 == message[3] || 0x39 == message[3]) {
			return true;
		}
		else if (0x37 == message[3] && 0x30 == message[4]) {
			return true;
		}
		
		return false;
	}
	
	private boolean sendFrameData(int frameIndex,int frameSize) {
		if (enumUpgradeHexType.enumUpgradeHexTypeSystem.ordinal() == enumUpgradeHexTypeWhat)
		{
			if (!mcuFileSystemRead.haveBinData())
			{
				return false;
			}
		}
		else
		{
			if (!mcuFileBootloaderRead.haveBinData())
			{
				return false;
			}
		}

		int sendSize;
		if (enumUpgradeHexType.enumUpgradeHexTypeSystem.ordinal() == enumUpgradeHexTypeWhat)
		{
			sendSize = mcuFileSystemRead.binData.length - frameIndex*frameSize;
		}
		else
		{
			sendSize = mcuFileBootloaderRead.binData.length - frameIndex*frameSize;
		}
		if (sendSize <= 0) {
			sendSize = 0;
		}
		
		if (sendSize > frameSize) {
			sendSize = frameSize;
		}
		
		Log.d("mcu_frame", String.format("send %d",frameIndex));
		
		byte[] buf = new byte[2+sendSize];
		buf[0] = (byte)(frameIndex & 0xff);
		buf[1] = (byte)((frameIndex >> 8) & 0xff);
		if (enumUpgradeHexType.enumUpgradeHexTypeSystem.ordinal() == enumUpgradeHexTypeWhat)
		{
			System.arraycopy(mcuFileSystemRead.binData, frameIndex*frameSize, buf, 2, sendSize);
			packAndMsgUseSelectID((byte)0x38,buf,buf.length);
		}
		else
		{
			System.arraycopy(mcuFileBootloaderRead.binData, frameIndex*frameSize, buf, 2, sendSize);
			packAndMsgUseSelectID((byte)0x39,buf,buf.length);
		}

		return true;	
	}

	public boolean isThreadFrameSendRun = false;
	
	private void sendFrameDataSeq() {
		if (isThreadFrameSendRun)
		{
			return;
		}
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				isThreadFrameSendRun = true;

				while (frameCountNow > 0)
				{		
					frameCountNow--;
					try  
			        {	
						if (!sendFrameData(frameIndexNow,frameSizeGet()))
						{
							break;
						}
						frameIndexNow++;
						
						if (enumUpgradeHexType.enumUpgradeHexTypeSystem.ordinal() == enumUpgradeHexTypeWhat)
						{
							showMCUVersion(true,frameIndexNow,mcuFileSystemRead.frameCountBinData(frameSizeGet()));
						}
						else
						{
							showMCUVersion(true,frameIndexNow,mcuFileBootloaderRead.frameCountBinData(frameSizeGet()));
						}
						
			            Thread.sleep(frameSendDelayGood(0));  
			        }  
			        catch (InterruptedException e)  
			        {  
			        } 
				}
				
				isThreadFrameSendRun = false;
			}
		}).start();
	}
	//////////////////////////////////////////////////////////////////frame send logic finish
	

	//////////////////////////////////////////////////////////
	public void reqMCUUUID(){
		byte[] buf = new byte[1];
		buf[0] = 0x14;
		packAndMsg(buf,buf.length);
	}
	
	public void reqMCUVersion(){
		byte[] buf = new byte[1];
		buf[0] = 0x12;
		packAndMsg(buf,buf.length);
	}
	
	String strMCUVersionDisplay = null;
	
	private void showMCUVersion(boolean bUpdating,int index,int count) {
		StringBuilder stringMCUVersion;
		
		if (count > 0 && index >= count)
		{
			bUpdating = false;
			recMCUVersion(mcuFileSystemRead.version);
		}
		
		if (isCorrectUpgradeFile()) {
			stringMCUVersion = new StringBuilder("  固件可更新到:");
			stringMCUVersion.append(String.format("%d", mcuFileSystemRead.version));
			stringMCUVersion.append("\r\n当前:");
		}
		else {
			stringMCUVersion = new StringBuilder("  固件版本: ");
		}
		
		if (bUpdating) {
			if (index >= count - 1)
			{
				stringMCUVersion.append(String.format("Finish!"));
			}
			else
			{
				if (enumUpgradeHexType.enumUpgradeHexTypeBootloader.ordinal() == enumUpgradeHexTypeWhat)
				{
					stringMCUVersion.append(String.format("BL "));			
				}
				stringMCUVersion.append(String.format("%d/%d@%dms@%d",index,count,frameSendDelayGood(99),BluetoothModel.getInstance().btWorkingHandler.msgBuffCount));			
			}			
		}
		else {
			if (AppModel.getInstance().getAgencyCode() != null && AppModel.getInstance().getAgencyCode().length() > 0) {
				stringMCUVersion.append(AppModel.getInstance().getAgencyCode());
				stringMCUVersion.append(":");						
			}
			stringMCUVersion.append(String.format("%d",versionMCU));		
		}
		if (upgradePassword != null && upgradePassword.length() > 0) {
			stringMCUVersion.append(String.format("$%s", upgradePassword));
		}
		Log.i("device", "mcu v:"+stringMCUVersion.toString());
		if (strMCUVersionDisplay == null || !strMCUVersionDisplay.equals(stringMCUVersion.toString())) {
			ViewModel.getIns().setViewProperty(R.id.mcu_version, stringMCUVersion.toString());
			ViewModel.getIns().refreshView(R.id.mcu_version);							
		}
	}
	
	boolean haveFetchMCUFile = false;
	
	public void readAndFetchMCUUpgradeFile(boolean bForceRead,boolean bReadFromService)
	{
		if (magicStringMCUString == null)
		{
			return;
		}
		
		if (bForceRead || !mcuFileSystemRead.isValidFile(magicStringMCUString))
		{
			mcuFileSystemRead.readHexFile(mcuSystemFileName,magicStringMCUString,true);
			
			if (mcuFileSystemRead.isValidFile(magicStringMCUString))
			{
				showMCUVersion(false,0,0);
			}			
		}
		if (bForceRead || !mcuFileBootloaderRead.haveBinData())
		{
			mcuFileBootloaderRead.readHexFile(mcuBootloaderFileName,magicStringMCUString,false);		
		}
		
		if (bReadFromService)
		{
			if (!haveFetchMCUFile)
			{
				haveFetchMCUFile = true;
				checkUpgradeFile();
				
			}
		}
	}
	
	private void recMCUMagicString(String magicString)
	{
		if (magicStringMCUString == null || !magicStringMCUString.equals(magicString))
		{
			magicStringMCUString = magicString;
			AppModel.getInstance().setModuleCode(magicStringMCUString);
			mcuSystemFileName = String.format("mcu_%s.hex", magicString);
			mcuBootloaderFileName = String.format("mcu_%s_Bootloader.hex", magicString);
			mcuSystemReqFlag = String.format("mcu_%s", magicString);
			mcuBootloaderReqFlag = String.format("mcu_%s_Bootloader", magicString);
			readAndFetchMCUUpgradeFile(false,true);
			showMCUVersion(false,0,0);
		}
	}

	private void recMCUVersion(int version)
	{
		if (versionMCU != version)
		{
			versionMCU = version;
			readAndFetchMCUUpgradeFile(false,true);
			showMCUVersion(false,0,0);
			if (versionMCU > 0 && versionMCU != 0xFFFFFFFF)
			{
				AppModel.getInstance().setModuleVersion(versionMCU);
			}
		}
	}
		
	public void checkVersion()
	{
		if (magicStringMCUString == null)
		{
			reqMCUNowStatus();
		}
		else if (0 == versionMCU)
		{
			reqMCUVersion();
		}
		else if (versionMCU != 0xFFFFFFFF)
		{
			if (CarModel.getInstance().devModule.getMcuUUID() == null)
			{
				reqMCUUUID();
			}
		}
	}
	
	public int enumUpgradeHexTypeWhat;
	
	private boolean needReloadFile = false;
	private boolean needRefetchFile = false;
	public int onRecvUpgradeMsg(byte[] message){//the message is packed
		/*final StringBuilder stringBuilder = new StringBuilder(message.length);
		for (byte byteChar : message)
			stringBuilder.append(String.format("%02X ", byteChar));
		Log.d("mcu_upgrade","onReceived: "+ stringBuilder.toString());*/
		
		if (needReloadFile)
		{
			needReloadFile = false;
			readAndFetchMCUUpgradeFile(true,false);
		}
		if (needRefetchFile)
		{
			needRefetchFile = false;
			showMCUVersion(false,0,0);
			readAndFetchMCUUpgradeFile(false,true);
		}
		if (0x37 == message[0])
		{
			switch (message[1])
			{
			case 0x11:
			{
				byte[] byteArray = new byte[8];
				System.arraycopy(message, 3, byteArray, 0, 8);
				String str = new String(byteArray);
				recMCUMagicString(str);
			}
				break;
			case 0x13:
			{
				byte[] byteArray = new byte[8];
				System.arraycopy(message, 2, byteArray, 0, 8);
				recMCUVersion(MCUUpgradeCommonFunction.transVersionToInt(byteArray));
			}
				break;
			case 0x15:
			{
				StringBuilder strMCUUUIDBuilder;
				strMCUUUIDBuilder = new StringBuilder();
				for (int i = 2;i < message.length;i++)
				{
					strMCUUUIDBuilder.append(String.format("%02x", message[i]));
				}
				CarModel.getInstance().devModule.setMcuUUID(strMCUUUIDBuilder.toString());
			}
				break;
			case 0x21:
			{
				byte[] byteArray = new byte[8];
				System.arraycopy(message, 2, byteArray, 0, 8);
				String str = new String(byteArray);
				recMCUMagicString(str);
				sendUpgradeSystemFileInfo();
			}
				break;
			case 0x29:
			{
				byte[] byteArray = new byte[8];
				System.arraycopy(message, 2, byteArray, 0, 8);
				String str = new String(byteArray);
				recMCUMagicString(str);
				sendUpgradeBootloaderFileInfo();
			}
				break;
			case 0x31:
			case 0x33:
				if (0x31 == message[1])
				{
					enumUpgradeHexTypeWhat = enumUpgradeHexType.enumUpgradeHexTypeSystem.ordinal();
				}
				else
				{
					enumUpgradeHexTypeWhat = enumUpgradeHexType.enumUpgradeHexTypeBootloader.ordinal();
				}
				int frameIndex = MCUUpgradeCommonFunction.getUnsignedByte(message[2]) + (MCUUpgradeCommonFunction.getUnsignedByte(message[3]) << 8);
				int frameSize = MCUUpgradeCommonFunction.getUnsignedByte(message[4]) + (MCUUpgradeCommonFunction.getUnsignedByte(message[5]) << 8);
				int frameReqMode = MCUUpgradeCommonFunction.getUnsignedByte(message[6]);
				int frameCount = MCUUpgradeCommonFunction.getUnsignedByte(message[7]) + (MCUUpgradeCommonFunction.getUnsignedByte(message[8]) << 8);
				
				frameSizeSet(frameSize);
				
				if (frameReqMode == enumFrameReqMode.enumFrameReqModeLost.ordinal())
				{
					Log.d("mcu_frame", String.format("rec lost %d",frameIndex));
					frameSendDelayGood(2);
					//sendFrameData(frameIndex,frameSizeGet());							
					frameCountNow = frameCount;	
					frameIndexNow = frameIndex;
				}
				else if (frameReqMode == enumFrameReqMode.enumFrameReqModeNormal.ordinal())
				{
					Log.d("mcu_frame", String.format("rec normal %d",frameIndex));
					if (frameIndexNow+frameCountNow != frameIndex)
					{
						frameSendDelayGood(2);
					}
					else
					{
						frameSendDelayGood(1);
					}
					frameCountNow = frameCount;				
					frameIndexNow = frameIndex;
				}
				
				sendFrameDataSeq();
				break;
			default:
				break;
			}
		}
		
		checkVersion();
		
		return 0;
	}
	
	@Override
	public void downloadUpdateContent(String fileName,String strContent,int version)
	{
		if (fileName.equals(mcuSystemFileName))
		{
			strUpdateContent = strContent;
			versionServiceSystem = version;
		}
		else if (fileName.equals(mcuBootloaderFileName))
		{
			versionServiceBootloader = version;
		}
	}
	
	@Override
	public void downloadServiceFileInfo(String fileName,String fileMD5,String fileUrl,int length)
	{
		if (fileName.equals(mcuSystemFileName))
		{			
			MCUFetchHex MCUFetchSystemInfo = new MCUFetchHex();
			MCUFetchSystemInfo.downloadFile(McuUpgradeModel.this, fileMD5, fileUrl, fileName);
		}
		else if (fileName.equals(mcuBootloaderFileName))
		{
			MCUFetchHex MCUFetchBootloaderInfo = new MCUFetchHex();
			MCUFetchBootloaderInfo.downloadFile(McuUpgradeModel.this, fileMD5, fileUrl, fileName);
		}
	}
	
	@Override
	public void downloadLocalIsNew(String fileName)
	{
		showMCUVersion(false,0,0);
	}
	
	@Override
	public void downloadReloadFile(String fileName)
	{
		needReloadFile = true;
		reqMCUNowStatus();
	}
}
